// Copyright (c) 2024 Go-Frame-Lite
// Go-Frame-Lite is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan
// PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//         http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.

// Package server provides HTTP server implementation and management functionality.
package server

import (
	"context"
	"net/http"
	"time"

	"go-frame-lite/pkg/configtypes"
	"go-frame-lite/pkg/logger"
	"go-frame-lite/pkg/middleware"
	"go-frame-lite/pkg/websocket"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

// Server 框架服务器
type Server struct {
	engine *gin.Engine
	srv    *http.Server
	hub    *websocket.Hub
}

// Config 服务器配置
type Config struct {
	Addr         string        // 监听地址
	ReadTimeout  time.Duration // 读取超时
	WriteTimeout time.Duration // 写入超时
	IdleTimeout  time.Duration // 空闲超时
	EnableWS     bool          // 是否启用WebSocket
}

// New 创建新的服务器实例
func New(config Config, monitorConfig *configtypes.MonitorConfig) *Server {
	// 设置Gin模式
	gin.SetMode(gin.ReleaseMode)

	engine := gin.New()

	// 如果传入的logger为nil，使用全局日志记录器
	// 中间件会使用全局日志，无需特殊处理

	// 添加基础中间件（使用全局日志版本，集成traceId）
	engine.Use(middleware.LoggerGlobal())
	engine.Use(middleware.RecoveryGlobal())

	// 添加Prometheus监控中间件
	if monitorConfig != nil && monitorConfig.Enabled {
		engine.Use(middleware.PrometheusMiddleware())
		// 注册指标路由
		middleware.RegisterMetricsRoute(engine, monitorConfig.MetricsPath)
	}

	// 添加国密中间件（根据配置启用）
	engine.Use(middleware.SM2SignatureMiddleware())
	engine.Use(middleware.SM4EncryptionMiddleware())

	srv := &http.Server{
		Addr:         config.Addr,
		Handler:      engine,
		ReadTimeout:  config.ReadTimeout,
		WriteTimeout: config.WriteTimeout,
		IdleTimeout:  config.IdleTimeout,
	}

	server := &Server{
		engine: engine,
		srv:    srv,
	}

	// 启用WebSocket
	if config.EnableWS {
		server.hub = websocket.NewHub()
		go server.hub.Run()
		// 将Hub添加到上下文中间件
		engine.Use(func(c *gin.Context) {
			c.Request = c.Request.WithContext(websocket.WithContext(c.Request.Context(), server.hub))
			c.Next()
		})
	}

	return server
}

// Engine 获取Gin引擎
func (s *Server) Engine() *gin.Engine {
	return s.engine
}

// Hub 返回WebSocket Hub实例
func (s *Server) Hub() *websocket.Hub {
	return s.hub
}

// Start 启动服务器
func (s *Server) Start() error {
	logger.Info(context.Background(), "服务器启动", zap.String("addr", s.srv.Addr))
	return s.srv.ListenAndServe()
}

// Shutdown 优雅关闭服务器
func (s *Server) Shutdown(ctx context.Context) error {
	logger.Info(ctx, "服务器正在关闭")
	return s.srv.Shutdown(ctx)
}
